package com.ngc.mall.controller;

import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ngc.mall.common.configure.response.ResponseResult;
import com.ngc.mall.common.configure.wxPay.WxCertificateConfig;
import com.ngc.mall.common.configure.wxPay.WxPaymentService;
import com.ngc.mall.core.enumeration.OrderStatus;
import com.ngc.mall.domain.OrderDomain;
import com.ngc.mall.service.IOrderService;
import com.ngc.mall.util.OrderStatusEnum;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@RestController
@RequestMapping("/payment")
public class   PaymentController {

   @Autowired
   private WxPaymentService wxPaymentService;

   @Autowired
   private IOrderService iOrderService;

   private static Lock lock = new ReentrantLock();
   /**
    * 生成预付订单
    * @param orderId
    * @return
    */
   @PostMapping("/pay/order/{orderId}")
   public ResponseResult<Map<String,String>> preOrder(@PathVariable Long orderId) throws UnrecoverableKeyException, CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException {
      return ResponseResult.success(wxPaymentService.preOrder(orderId));
   }
   private String getRequestBody(HttpServletRequest request){
      StringBuffer sb = new StringBuffer();

      try (ServletInputStream inputStream = request.getInputStream();
           BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
      ) {
         String line;

         while ((line = reader.readLine()) != null) {
            sb.append(line);
         }

      } catch (IOException e) {
        e.printStackTrace();
      }

      return sb.toString();

   }
   /**
    * 支付通知回调函数
    */
   @RequestMapping("/wx/notify")
   public JSONObject payCallback( HttpServletRequest request,
                                           HttpServletResponse response) {
      System.out.println("-----------------微信支付回调-------------");
      JSONObject wxPayResponse=new JSONObject();
      if(lock.tryLock()){
         String jsonData=getRequestBody(request);
         System.out.println(jsonData);
         String signature = request.getHeader("Wechatpay-Signature");
         String nonce = request.getHeader("Wechatpay-Nonce");
         String serial = request.getHeader("Wechatpay-Serial");
         String timestamp = request.getHeader("Wechatpay-Timestamp");
         String signType=request.getHeader("Wechatpay-Signature-Type");
         String merchantSerialNumber=request.getHeader("Wechatpay-Serial");
         // 初始化 NotificationParser
         NotificationParser parser = new NotificationParser(WxCertificateConfig.getInstance().getNotificationConfig());
         RequestParam requestParam =
                 new RequestParam.Builder()
                         .serialNumber(merchantSerialNumber)
                         .nonce(nonce)
                         .signature(signature)
                         .signType(signType)
                         .timestamp(timestamp)
                         .body(jsonData)
                         .build();
         // 以支付通知回调为例，验签、解密并转换成 Transaction
         try{
            Transaction transaction = parser.parse(requestParam, Transaction.class);
            System.out.println(transaction);
            response.setStatus(HttpServletResponse.SC_OK);
            if(transaction.getTradeState()== Transaction.TradeStateEnum.SUCCESS){
               iOrderService.update(Wrappers.<OrderDomain>lambdaUpdate()
                       .eq(OrderDomain::getId,transaction.getOutTradeNo())
                       .set(OrderDomain::getTransactionId,transaction.getTransactionId())
                       .set(OrderDomain::getStatus, OrderStatus.PAID.getValue())
                       .set(OrderDomain::getPaymentTime, LocalDateTime.parse(transaction.getSuccessTime(), DateTimeFormatter.ISO_OFFSET_DATE_TIME))
               );
            }
            return null;
         }catch (Exception e){
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            wxPayResponse.putOpt("code","fail");
            wxPayResponse.putOpt("message","失败");
            return wxPayResponse;
         }finally {
            lock.unlock();
         }
      }
      response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
      wxPayResponse.putOpt("code","fail");
      wxPayResponse.putOpt("message","失败");
      return wxPayResponse;
   }

   @RequestMapping("/test")
   public boolean testOrder(){
      return iOrderService.update(Wrappers.<OrderDomain>lambdaUpdate()
              .eq(OrderDomain::getId,"1657389535540232194")
              .set(OrderDomain::getTransactionId,"4200001861202305137747462168")
              .set(OrderDomain::getStatus, OrderStatusEnum.NOT_SHIPPED.getStatus())
              .set(OrderDomain::getPaymentTime,LocalDateTime.parse("2023-05-13T22:17:22+08:00", DateTimeFormatter.ISO_OFFSET_DATE_TIME))
      );
   }
}
